﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ClosedXML.Excel;
using System.IO;
using DTO;
using System.Linq;
using ModelAccess.Concrete;
using ModelLayer;
using System.Data.Common;
namespace BusinessLayer.Logic.ReportProducer
{
    public class ExcelImportUtenti
    {


        public IXLCells getCells(IXLColumn column,int numRow)
        {
            if (column == null)
                return null;
            int rowNumberHeader = column.FirstCellUsed().Address.RowNumber;
            int rowNumberLast;
            if (numRow == -1)
                rowNumberLast = column.LastCellUsed().Address.RowNumber;
            else
                rowNumberLast = rowNumberHeader + numRow;
            return column.Cells(rowNumberHeader + 1, rowNumberLast);
        }

        private static Random random = new Random((int)DateTime.Now.Ticks);
        private string createRandomPassword()
        {
            int size = 8;
            StringBuilder builder = new StringBuilder();
            char ch;
            for (int i = 0; i < size; i++)
            {
                ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));
                builder.Append(ch);
            }

            return builder.ToString();
        }


        private void scriviFileElaborato(IXLWorksheet elaborazioneWs, int row, String username, String name, String cognome, String email, String password, String esito)
        {

            elaborazioneWs.Row(row).Cell(1).Value = username;
            elaborazioneWs.Row(row).Cell(2).Value = name;
            elaborazioneWs.Row(row).Cell(3).Value = cognome;
            elaborazioneWs.Row(row).Cell(4).Value = email;
            elaborazioneWs.Row(row).Cell(5).Value = password;
            if (esito != null)
            {
                elaborazioneWs.Row(row).Cell(6).Value = esito;
                if (esito.CompareTo("OK") != 0 && esito.CompareTo("Esito") != 0)
                {
                    elaborazioneWs.Row(row).Style.Fill.BackgroundColor = XLColor.Red;
                }
            }
        }
        private void insertError(IXLWorksheet elaborazioneWs, String error)
        {
            IXLRange range = elaborazioneWs.LastRowUsed().RowBelow().Merge();
            IXLCell cell = range.FirstCell();
            cell.Style.Fill.BackgroundColor = XLColor.Red;
            cell.Value = error;
        }
        public byte[] getTemplate()
        {
            XLWorkbook wb = new XLWorkbook();
            IXLWorksheet ws = wb.AddWorksheet("INFO", 1);
            IXLWorksheet utenti= wb.AddWorksheet("UTENTI",2);

            IXLRange range = ws.Range(1, 1, 50, 50).Merge();

            IXLCell cell = range.FirstCell();
            cell.Value = "Questo è un file template per l'import degli utenti. Inserire le informazioni nella tabella della pagine UTENTI"
                           + Environment.NewLine +
                          "Tutti i campi ad eccezione di username sono opzionali. Se non sono presenti verrano generati dal sistema."
                           + Environment.NewLine +
                           "Nel caso non venga inserita la password per uno piu utenti, questa verrà generata randomicamente."
                            + Environment.NewLine +
                            "A fine export verrà presentato all'utente lo stesso file excel con una nuova pagina contenente eventuali errori ed utenti inseriti"
                             + Environment.NewLine +
                             "In questa pagina di ripilogo si potranno reperire anche le informazioni che il sistema ha autogenerato come, eventualmente, la password";


            cell.Style.Alignment.Vertical=XLAlignmentVerticalValues.Top;
            cell.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Left;

            scriviFileElaborato(utenti,1, "Username", "Nome", "Cognome", "Email", "Password", null);
            scriviFileElaborato(utenti, 2, "TEST", "TEST", "TEST", "TEST", "TEST", null);
            MemoryStream outs = new MemoryStream();
            wb.SaveAs(outs);
            byte[] savedFile = outs.ToArray();
            outs.Close();
            return savedFile;
           
        }
        public byte[] import(byte[] p, Utente superiore)
        {

            XLWorkbook wb;
            MemoryStream ms = new MemoryStream(p);
            wb = new XLWorkbook(ms);
            IXLWorksheet ws = wb.Worksheet("UTENTI");
            IXLWorksheet oldElaborazione=wb.Worksheets.Where(x=>x.Name=="Elaborazione").FirstOrDefault();
            if (oldElaborazione!=null)
            {
                oldElaborazione.Delete();
            }
            IXLWorksheet elaborazioneWs = wb.AddWorksheet("Elaborazione", 1);
             bool inserted = true;
            try
            {

                IXLColumn usernameColumn = ws.ColumnsUsed(x => x.FirstCellUsed().Value.ToString().ToLower() == "username").FirstOrDefault();
                IXLColumn nomeColumn = ws.ColumnsUsed(x => x.FirstCellUsed().Value.ToString().ToLower() == "nome").FirstOrDefault();
                IXLColumn cognomeColumn = ws.ColumnsUsed(x => x.FirstCellUsed().Value.ToString().ToLower() == "cognome").FirstOrDefault();
                IXLColumn emailColumn = ws.ColumnsUsed(x => x.FirstCellUsed().Value.ToString().ToLower() == "email").FirstOrDefault();
                IXLColumn passwordColumn = ws.ColumnsUsed(x => x.FirstCellUsed().Value.ToString().ToLower() == "password").FirstOrDefault();
                UtenteLogic ul = new UtenteLogic();
                if (usernameColumn == null)
                    throw new Exception("Impossibile trovare la colonna username. File errato");
                
                IXLCells usernames = getCells(usernameColumn,-1);
                int numUtenti = usernames.Count();
                IXLRange range = elaborazioneWs.Row(1).Merge();
                range.Cell(1, 1).Value = "Trovati " + numUtenti + " utenti da importare";
                scriviFileElaborato(elaborazioneWs, 2, "Username", "Nome", "Cognome", "Email", "Password", "Esito");
                IXLCells nomes = null;
                IXLCells cognomes = null;
                IXLCells passwords = null;
                IXLCells emails = null;
                nomes = getCells(nomeColumn,numUtenti);
                cognomes = getCells(cognomeColumn, numUtenti);
                emails = getCells(emailColumn, numUtenti);
                passwords = getCells(passwordColumn, numUtenti);

                List<DTOUtente> utenti = new List<DTOUtente>();
                int rowElaborata = 3;
               
                using (UtentiHelper uh = new UtentiHelper())
                {
                    DbTransaction transaction = null;
                    try
                    {
                        transaction = uh.startTransaction();
                        UtenteLogic logic = new UtenteLogic();
                        for (int i = 0; i < numUtenti; i++)
                        {
                            IXLCell usernameCell = usernames.ElementAt(i);
                            Utente utente = new Utente();
                            utente.Username = usernameCell.Value.ToString();
                            if (nomes != null)
                                utente.Nome = nomes.ElementAt(i).Value.ToString();
                            if (cognomes != null)
                                utente.Cognome = cognomes.ElementAt(i).Value.ToString();
                            if (passwords != null)
                                utente.Password = passwords.ElementAt(i).Value.ToString();
                            if (emails != null)
                                utente.Email = emails.ElementAt(i).Value.ToString();
                            
                            if(utente.Nome==null||utente.Nome=="")
                             utente.Nome = "user";
                            if (utente.Cognome == null || utente.Cognome == "")
                             utente.Cognome = "user";
                            if (utente.Password == null || utente.Password == "")
                                utente.Password = createRandomPassword();
                            if (utente.Email == null || utente.Email == "")
                                utente.Email = "user@user.it";

                            String plainPassword = utente.Password;
                            String esito = "OK";
                            try
                            {
                                if (!logic.inserisciUsingConnection(utente, superiore, uh))
                                {
                                    esito = "Username gia esistente";
                                    inserted = false;
                                }
                            }
                            catch (Exception e)
                            {
                                esito = "Errore nell'inserimento: " + e.Message;
                                inserted = false;
                                break;
                            }
                            scriviFileElaborato(elaborazioneWs, rowElaborata, utente.Username, utente.Nome, utente.Cognome, utente.Email, plainPassword, esito);
                            rowElaborata++;


                        }
                    }
                    catch (Exception e)
                    {
                        inserted = false;
                        insertError(elaborazioneWs,"Errore nell'elaborazione! " + e.Message);
                       
                    }
                    finally
                    {
                        if (transaction != null)
                            if (inserted == true)
                                uh.commit(transaction);
                            else
                                uh.rollback(transaction);
                    }
                }

            }
            catch (Exception e)
            {
                inserted = false;
                insertError(elaborazioneWs,"Errore nell'elaborazione! " + e.Message);
            }
            if (!inserted)
            {
                insertError(elaborazioneWs, "Gli utenti non sono stati inseriti a causa di un errore. Risolverli e riprovare!"); 
            }
            MemoryStream outs = new MemoryStream();
            
            wb.SaveAs(outs);
            byte[] savedFile = outs.ToArray();
            ms.Close();
            outs.Close();
            return savedFile;
        }
    }
}
